package com.hontech.kaltaapp.serial

import com.hontech.kaltaapp.R
import com.hontech.kaltaapp.device.Proto
import com.hontech.kaltaapp.device.RecvFrame
import com.hontech.kaltaapp.exception.PackageInvalidException
import com.hontech.kaltaapp.utils.ConnTask
import com.hontech.kaltaapp.utils.runAsync
import com.hontech.kaltaapp.utils.stringById
import com.hontech.kaltaapp.utils.stringsById
import com.hontech.kaltaapp.utils.toHexs
import com.hontech.kaltaapp.utils.toU8
import com.hontech.kaltaapp.utils.xorSum

interface SerialPort {

    companion object {
        val USB_PORT_NAME = stringById(R.string.name_usb)
        val SERIAL_PORT_NAMES = stringsById(R.array.serial_ports)
    }

    fun sync(): Int

    fun readBytes(buf: ByteArray): Int

    fun close()

    fun notifyClose()

    fun write(buf: ByteArray)

    fun readOnce(): RecvFrame {
        val len = sync()
        if (len < 7) {
            throw PackageInvalidException("len < 7 => $len")
        }
        val buf = ByteArray(len - 3)
        readBytes(buf)

        val sum = xorSum(buf, 0, buf.size - 2)
        val s = buf[buf.size - 2].toU8()
        if (s != sum) {
            throw PackageInvalidException("校验和错误: $s $sum ${buf.toHexs()}")
        }

        if (buf[buf.size - 1].toU8() != Proto.END) {
            throw PackageInvalidException("包尾部错误")
        }

        return RecvFrame(buf)
    }

    fun writeForAsync(buf: ByteArray) {
        ConnTask.post { write(buf) }
    }

    suspend fun writeForAwait(buf: ByteArray) {
        runAsync { write(buf) }
    }
}

